package nrpc.client.serst;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Collection;
import java.util.Map;
import java.util.function.Consumer;

import nrpc.client.ClientStub;
import nrpc.impl.RegisterHandler;
import nrpc.impl.SubscriberHandler;
import nrpc.message.meta.ServerEntry;
import nrpc.server.ServerStub;

public class SubscribeServiceStrategy implements ServiceStrategy {

	private ClientStub subscriber;
	private ServerStub thisStub;
	private RegisterHandler handler;
	private String url;
	private long id;
	
	public SubscribeServiceStrategy(InetSocketAddress registerAddress, String url) {
		
		try {
			subscriber = new ClientStub(registerAddress);
			thisStub = new ServerStub();
		} catch (IOException e) { 
			e.printStackTrace();
		}
		this.url = url;
		this.handler = subscriber.getProxyInstance(RegisterHandler.class);
		
	}
	
	@Override
	public void subscribe(Consumer<? super ServiceNode> add, Consumer<? super ServiceNode> delete) {
		try {
			thisStub.registerInstance(new SubscriberHandler() {
				private Map<Long, ServiceNode> map = new HashMap<>();
				@Override
				public void deleteServer(long id) {
					delete.accept(map.remove(id));
//					callback.accept(map.values());
					
				}
				@Override
				public void addServer(long id, ServerEntry serverEntry) {
					AddressServiceNode node = new AddressServiceNode(serverEntry.host, serverEntry.port);
					add.accept(node);
					map.put(id, node);
//					callback.accept(map.values());
				}
			}, SubscriberHandler.class);
		} catch (IOException e) {
			e.printStackTrace();
		}
		InetSocketAddress localAddress = this.thisStub.getLocalAddress();
		id = handler.subscribe(this.url, localAddress.getHostName(), localAddress.getPort());
	}

	private boolean closed;
	@Override
	public synchronized void close() {
		if(!closed) {
			this.closed = true;
			this.handler.cancelSubscribe(url, id);
			this.subscriber.close();
			this.thisStub.close();	
		}
	}
	
}
